int add_name_to_parent(MINODE* parent, ulong inode, char* name)
{
	int recordLength = ((strlen(name) + 11) / 4) * 4;
	int i, j, device = 0;
	char buf[MAX_BLOCK_SIZE], *pnt;
	EXT2_DISK* diskInfo;
	SUPER super;
	
	if (parent->mounted == true)
		device = parent->mountedDevice->handle;
	else
		device = parent->location.deviceHandle;
		
	if (get_device_info(device, &diskInfo) == -1)
		return -1;
	
	/* Look through direct data blocks */
	for (i = 0; i < NUM_DIRECT_BLOCKS; i++)
	{
		if (parent->inode.i_block[i] != 0)
		{
			if (read_blk(device, parent->inode.i_block[i], diskInfo->blockSize, buf) == -1)
				return -1;
				
			pnt = buf; j = 0;
			while (j < diskInfo->blockSize)
			{
				/* Found place for new name */
				if ((((DIR*)pnt)->rec_len - recordLength) >= recordLength)
				{
					/* Need to split current entry */
					if ((((((DIR*)pnt)->name_len + 11) / 4) * 4) < ((DIR*)pnt)->rec_len)
					{
						int new_len = ((DIR*)pnt)->rec_len - (((((DIR*)pnt)->name_len + 11) / 4) * 4);
						((DIR*)pnt)->rec_len = (((((DIR*)pnt)->name_len + 11) / 4) * 4);
						pnt += ((DIR*)pnt)->rec_len;
						
						((DIR*)pnt)->inode = inode;
						((DIR*)pnt)->rec_len = new_len;
						((DIR*)pnt)->name_len = strlen(name);
						strncpy(((DIR*)pnt)->name, name, strlen(name));
					}
					/* Add new entry to end */
					else
					{
						((DIR*)pnt)->rec_len = ((((DIR*)pnt)->name_len + 11) / 4) * 4;
						pnt += ((DIR*)pnt)->rec_len;
						
						((DIR*)pnt)->inode = inode;
						((DIR*)pnt)->rec_len = diskInfo->blockSize - (pnt - buf);
						((DIR*)pnt)->name_len = strlen(name);
						strncpy(((DIR*)pnt)->name, name, strlen(name));
					}
					if (write_blk(device, parent->inode.i_block[i], diskInfo->blockSize, buf) == -1)
							return -1;
					return 1;
				}
				j += ((DIR*)pnt)->rec_len;
				pnt += ((DIR*)pnt)->rec_len;
			}
		}
	}
	
	/* Will get here if no room for entry, so allocate new block */
	if (get_super(device, &super) == -1)
		return -1;
	
	for (i = 0; i < NUM_DIRECT_BLOCKS; i++)
	{
		if (parent->inode.i_block[i] == 0)
		{
			char buf[MAX_BLOCK_SIZE];
			DIR newEntry;
			
			parent->inode.i_block[i] = allocate_free_block(device,
				(parent->location.inodeNum - 1) / super.s_inodes_per_group);
			if (parent->inode.i_block[i] != 0)
			{
				parent->inode.i_blocks += (diskInfo->blockSize / SECTOR_SIZE);
				
				((DIR*)buf)->inode = inode;
				((DIR*)buf)->rec_len = diskInfo->blockSize;
				((DIR*)buf)->name_len = strlen(name);
				strncpy(((DIR*)buf)->name, name, strlen(name));
				
				if (write_blk(device, parent->inode.i_block[i], diskInfo->blockSize, buf) == -1)
					return -1;
					
				return 1;
			}
		}
	}
	
	return -1;
}

int my_mkdir(MINODE* parent, char* dirName)
{
	int i = 0, blockGroup = 0, device = 0;
	ulong dirInode = 0, dirBlock = 0;
	char buf[MAX_BLOCK_SIZE], *pnt = buf;
	EXT2_DISK* diskInfo;
	MINODE* newDir;
	SUPER super;
	
	/* If the parent is a mounted inode */
	if (parent->mounted == true)
		device = parent->mountedDevice->handle;
	else
		device = parent->location.deviceHandle;
		
	if (get_device_info(device, &diskInfo) == -1)
		return -1;
	
	if (get_super(device, &super) == -1)
		return -1;
		
	dirInode = allocate_free_inode(device);
	
	if (dirInode == 0)
		return -1;
	
	/* Try to allocate a block */
	blockGroup = (dirInode - 1) / super.s_inodes_per_group;
	for (i = 0; ((i < diskInfo->numGroups) && (dirBlock == 0)); i++)
	{
		dirBlock = allocate_free_block(device, blockGroup);
		if (dirBlock == 0)
		{
			if (blockGroup == diskInfo->numGroups)
				blockGroup = 0;
			else
				blockGroup++;
		}
	}
	
	/* Disk full */
	if (i > diskInfo->numGroups)
	{
		deallocate_inode(device, dirInode);
		return -1;
	}
	
	/* Load inode into memory */
	newDir = get_inode(device, dirInode);
	if (newDir == 0)
	{
		deallocate_block(device, dirBlock);
		deallocate_inode(device, dirInode);
		return -1;
	}
	
	/* Fill in data for new inode and write to disk */
	newDir->inode.i_mode = DEFAULT_DIR_MODE;
	newDir->inode.i_uid = runningProc->uid;
	newDir->inode.i_gid = runningProc->gid;
	newDir->inode.i_size = diskInfo->blockSize;
	newDir->inode.i_links_count = 2;
	newDir->inode.i_atime = newDir->inode.i_ctime = newDir->inode.i_mtime = time(0);
	newDir->inode.i_blocks = diskInfo->blockSize / SECTOR_SIZE;
	newDir->inode.i_block[0] = dirBlock;
	newDir->dirty = true;
	for (i = 1; i < 15; i++)
		newDir->inode.i_block[i] = 0;
	put_inode(newDir);
	
	/* Create . and .. entries in dir block */
	((DIR*)pnt)->inode		= dirInode;
	((DIR*)pnt)->name_len	= 1;
	((DIR*)pnt)->rec_len	= 12;
	strncpy(((DIR*)pnt)->name, ".", 1);
	
	pnt += 12;
	
	if (parent->mounted == true)
		((DIR*)pnt)->inode	= ROOT_INODE;
	else
		((DIR*)pnt)->inode	= parent->location.inodeNum;
	((DIR*)pnt)->name_len	= 2;
	((DIR*)pnt)->rec_len	= diskInfo->blockSize - 12;
	strncpy(((DIR*)pnt)->name, "..", 2);
	
	/* Write new dir block to disk */
	if (write_blk(device, dirBlock, diskInfo->blockSize, buf) == -1)
	{
		deallocate_block(device, dirBlock);
		deallocate_inode(device, dirInode);
		return -1;
	}
	
	/* Write new dirName into parents blocks */
	if (add_name_to_parent(parent, dirInode, dirName) == -1)
	{
		deallocate_block(device, dirBlock);
		deallocate_inode(device, dirInode);
		return -1;
	}
	
	/* Update parent information and write back to disk */
	parent->inode.i_links_count++;
	parent->inode.i_atime = time(0);
	parent->dirty = true;
	put_inode(parent);
	
	return 1;
}

int do_mkdir(char* pathName)
{
	LOC dirInodeLoc;
	char fullPath[MAX_PATH_LENGTH];
	char dirName[MAX_PATH_LENGTH];
	char baseName[EXT2_MAX_FILE_LENGTH];
	MINODE* dirInode;
	
	if (pathName[0] != '/')
	{
		get_pwd_name(runningProc->cwd, fullPath);
		strcat(fullPath, pathName);
	}
	else
		strcpy(fullPath, pathName);
		
	dir_name(fullPath, dirName);
	base_name(fullPath, baseName);
	
	dirInodeLoc = get_inode_number(dirName);
	if (dirInodeLoc.inodeNum == 0)
	{
		printf("\"%s\" does not exist\n\n", pathName);
		return -1;
	}
	
	dirInode = get_inode(dirInodeLoc.deviceHandle, dirInodeLoc.inodeNum);
	if (dirInode == 0)
		return -1;
		
	if (S_ISDIR(dirInode->inode.i_mode))
	{
		if (search_inode(dirInode, baseName) == 0)
			return my_mkdir(dirInode, baseName);
		
		printf("\"%s\" already exists\n\n", pathName);
		return -1;
	}
	
	printf("\"%s\" is not a directory\n\n", dirName);
	return -1;
}
